home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / mtools.lha / mtools-2.0.7 / buf_write.c < prev    next >
C/C++ Source or Header  |  1992-09-10  |  3KB  |  137 lines

  1. /*
  2.  * Do full cylinder buffered writes to slow devices.  Uses a simple
  3.  * buffered read/delayed write algorithm
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "msdos.h"
  8.  
  9. extern int fd, disk_size, disk_dirty, dir_start, dir_len;
  10. extern int clus_size;
  11. extern long disk_offset, disk_current;
  12. extern unsigned char *disk_buf;
  13. static int read_cyl();
  14.  
  15. void
  16. disk_write(start, buf, len)
  17. long start;
  18. unsigned char *buf;
  19. int len;
  20. {
  21.     register long i;
  22.     int length;
  23.     unsigned char *buf_ptr, *disk_ptr;
  24.     char *memcpy();
  25.     void perror(), exit(), disk_flush();
  26.     long where, tail, lseek();
  27.  
  28.                     /* don't use cache? */
  29.     if (disk_size == 1) {
  30.         where = (start * MSECTOR_SIZE) + disk_offset;
  31.         if (lseek(fd, where, 0) < 0) {
  32.             perror("disk_write: lseek");
  33.             exit(1);
  34.         }
  35.                     /* write it! */
  36.         if (write(fd, (char *) buf, (unsigned int) len) != len) {
  37.             perror("disk_write: write");
  38.             exit(1);
  39.         }
  40.         return;
  41.     }
  42.  
  43.     tail = start + (len / MSECTOR_SIZE) - 1;
  44.     for (i = start; i <= tail; i++) {
  45.                     /* a cache miss... */
  46.         if (i < disk_current || i >= disk_current + disk_size) {
  47.  
  48.             if (disk_dirty)
  49.                 disk_flush();
  50.  
  51.             disk_current = (i / disk_size) * disk_size;
  52.             /*
  53.              * If there is something on the new cylinder that
  54.              * you want to keep, you'll have to read it first
  55.              * before writing.
  56.              */
  57.             if (read_cyl(disk_current)) {
  58.                 where = (disk_current * MSECTOR_SIZE) + disk_offset;
  59.                 length = disk_size * MSECTOR_SIZE;
  60.  
  61.                     /* move to next location */
  62.                 if (lseek(fd, where, 0) < 0) {
  63.                     perror("disk_write: lseek");
  64.                     exit(1);
  65.                 }
  66.                     /* read it! */
  67.                 if (read(fd, (char *) disk_buf, (unsigned int) length) != length) {
  68.                     perror("disk_write: read");
  69.                     exit(1);
  70.                 }
  71.             }
  72.         }
  73.                     /* a cache hit ... */
  74.         buf_ptr = buf + ((i - start) * MSECTOR_SIZE);
  75.         disk_ptr = disk_buf + ((i - disk_current) * MSECTOR_SIZE);
  76.         memcpy((char *) disk_ptr, (char *) buf_ptr, MSECTOR_SIZE);
  77.         disk_dirty = 1;
  78.     }
  79.     return;
  80. }
  81.  
  82. /*
  83.  * Flush a dirty buffer to disk.  Resets disk_dirty to zero.
  84.  * All errors are fatal.
  85.  */
  86.  
  87. void
  88. disk_flush()
  89. {
  90.     int len;
  91.     long where, lseek();
  92.     void perror(), exit();
  93.  
  94.     if (fd < 0 || disk_current < 0L || !disk_dirty)
  95.         return;
  96.  
  97.     where = (disk_current * MSECTOR_SIZE) + disk_offset;
  98.     if (lseek(fd, where, 0) < 0) {
  99.         perror("disk_flush: lseek");
  100.         exit(1);
  101.     }
  102.                     /* write it! */
  103.     len = disk_size * MSECTOR_SIZE;
  104.     if (write(fd, (char *) disk_buf, (unsigned int) len) != len) {
  105.         perror("disk_flush: write");
  106.         exit(1);
  107.     }
  108.     disk_dirty = 0;
  109.     return;
  110. }
  111.  
  112. /*
  113.  * Determine if the cylinder has some useful information on it.  Returns a 1
  114.  * if it needs to be read.
  115.  */
  116.  
  117. static int
  118. read_cyl(sector)
  119. long sector;
  120. {
  121.     register unsigned int i;
  122.     unsigned int start, end, fat_decode();
  123.  
  124.     if (!sector)
  125.         return(1);
  126.  
  127.     start = ((sector - dir_start - dir_len) / clus_size) + 2;
  128.     end = ((sector + disk_size - dir_start - dir_len) / clus_size) + 2;
  129.  
  130.     for (i = start; i < end; i++) {
  131.                     /* if fat_decode returns non-zero */
  132.         if (fat_decode(i))
  133.             return(1);
  134.     }
  135.     return(0);
  136. }
  137.